﻿using System;
using System.Diagnostics;
using SG.Sys.Console.CommandProcessing;
using SG.Sys.Console.Process;
using SG.Sys.Console.Properties;

namespace SG.Sys.Console.Implementation
{
    public class Utf8CmdWrapper : ProcessWrapperBase
    {
        public Utf8CmdWrapper()
            : base(new ProcessStartInfo("cmd.exe", "/e:on /v:on /a"), '>')
        {
            // nothing to do yet
        }

        public override void SendClose()
        {
            var stdIn = Process.StandardInput;
            stdIn.WriteLine("exit");
        }

        public override StateChange SendCommand(Entry entry)
        {
            var hasArgs = !string.IsNullOrWhiteSpace(entry.Command.ArgumentsJoined);

            switch (entry.Command.Executable.ToLowerInvariant())
            {
                case "exit":
                    return StateChange.UserIssuedExit;

                case "title":
                    if (hasArgs)
                    {
                        Title = entry.Command.ArgumentsJoined;
                        return StateChange.TitleChange;
                    }
                    throw new ArgumentException(Resources.Utf8CmdWrapper_SendCommand_No_title_specified_, "entry");

                case "history":
                    return StateChange.DisplayHistory;
            }

            Process.StandardInput.WriteLine(entry.Command);
            return StateChange.None;
        }

        public override Command ParseCommand(string cmdLine)
        {
            cmdLine = cmdLine.Trim();

            SpecialCaseChangeDir(ref cmdLine);

            var indexOfArgs = cmdLine.IndexOfAny(new[] {'/', ' '});
            var hasArgs = indexOfArgs > 0;

            string exe, argsJoined;
            if (hasArgs)
            {
                exe = cmdLine.Substring(0, indexOfArgs);
                var isWhitespace = char.IsWhiteSpace(cmdLine[indexOfArgs]);
                argsJoined = cmdLine.Substring(indexOfArgs + (isWhitespace ? 1 : 0));
            }
            else
            {
                exe = cmdLine;
                argsJoined = null;
            }

            // TODO is wrong, but works for now
            var args = argsJoined == null ? null : argsJoined.Split(' ');

            return new Command(cmdLine, exe, args);
        }

        private static void SpecialCaseChangeDir(ref string cmdLine)
        {
            const string changeDir = "cd";
            var dirIndex = changeDir.Length;

            if (cmdLine.Length > dirIndex
                && cmdLine.StartsWith(changeDir, StringComparison.InvariantCultureIgnoreCase)
                && !char.IsLetterOrDigit(cmdLine[dirIndex]))
            {
                cmdLine = changeDir + " " + cmdLine.Substring(dirIndex);
            }
        }
    }
}
